# -*- coding:utf-8 -*-

from .base_handler import BaseRequestHandler
import json
import time
import datetime
import tornado.log


class UserLoginHandler(BaseRequestHandler):
    login_notes = {}  # {username: {error_times:1, locked_end_time: time}, ip: {error_times:1, locked_end_time: time}}
    @classmethod
    async def update_user_token(self, token_info: dict, user_id: str or int):
        d = {
            'lt': time.time(),
        }
        d.update(token_info)
        user_token = self.encryption.token_enc(json.dumps(d, ensure_ascii=False))
        await self.mdb.update_by_dict(
            table='tdp_user',
            colv={
                'token': user_token,
                'token_expire_time': (datetime.datetime.now() + datetime.timedelta(hours=5)).strftime(
                    "%Y-%m-%d %H:%M:%S")
            },
            where={'id': user_id}
        )
        return user_token

    async def post_default(self):
        async def add_and_check_times(key):
            if self.login_notes.get(key):
                self.login_notes[key]['error_times'] += 1
                error_times = self.login_notes[key]['error_times']
                locked_end_time = self.login_notes[key]['locked_end_time']
                if error_times >= 6:
                    await self.mdb.execute('update tdp_user set status=%s where user_name=%s', 'login_locked', user_name)
                    for k in (user_name, self.request.remote_ip):
                        try:
                            self.login_notes.pop(k)
                        except:
                            pass
                    raise Exception('您的账号因多次密码输入错误已被锁定，请联系管理员解锁！')
                elif error_times >= 3 and not locked_end_time:
                    self.login_notes[key]['locked_end_time'] = time.time() + 30*60
                    raise Exception('密码输入错误3次，请30分钟后再试！')
            else:
                self.login_notes[key] = {'error_times':1, 'locked_end_time': None}

        def check_login_limit(user_name):
            """检查用户密码、ip错误次数是否达到上限"""
            def check(key):
                if self.login_notes.get(key):
                    error_times = self.login_notes[key]['error_times']
                    locked_end_time = self.login_notes[key]['locked_end_time']
                    if error_times >= 3 and time.time() < locked_end_time:
                        print(self.login_notes)
                        raise Exception('密码输入错误3次，请30分钟后再试！')
            check(self.request.remote_ip)
            check(user_name)

        user_name = self.request_json.get('username', '')
        passwd = self.request_json.get('passwd', '')
        check_login_limit(user_name)
        user_info = await self.mdb.query_one_by_dict(
            table='tdp_user',
            col=('real_name', 'passwd','id', 'status', 'UNIX_TIMESTAMP(`token_expire_time`) as token_expire_time', 'token'),
            where={'user_name': user_name},
            where_excepted=tuple()
        )
        if not user_info:
            await add_and_check_times(self.request.remote_ip)
            raise Exception("用户名或密码错误，请重试！")
        else:
            if user_info['status'] == 'login_locked':
                raise Exception('您的账号因多次密码输入错误已被锁定，请联系管理员解锁！')
            user_id = user_info['id']
            enc_pwd = user_info.get('passwd', '')
            if passwd != self.encryption.passwd_dec(enc_pwd):
                await add_and_check_times(user_name)
                raise Exception('用户名或密码错误，请重试！')
            else:
                for k in (user_name, self.request.remote_ip):
                    try:
                        self.login_notes.pop(k)
                    except:
                        pass
                ret_code = 0
                ret_msg = '密码正确'
                if user_info['token'] and user_info['token_expire_time']>time.time():
                    user_token = user_info['token']
                else:
                    user_token = await self.update_user_token(
                        token_info={'i': user_id, 'n': user_name, 'rn': user_info['real_name']},
                        user_id=user_id
                    )
        self.set_cookie('token', user_token)
        self.success_data = user_token
        self.success_msg = ret_msg
        self.exception_code = ret_code

    async def get_sso(self):
        sso_token = self.get_argument('sso_token', '')
        if sso_token == 'cf620c803322e8776b5380b9b73100fb90403ecc38256d47e35d17694d4':  # 后台交互token
            tornado.log.access_log.info(f'后端sso_token 验证通过！')
            user_id = self.get_argument('user_id')
            user_name = self.get_argument('user_name')
            real_name = self.get_argument('real_name')
            if not user_id or not user_name:
                raise Exception('缺少用户参数！')
            user_info = await self.mdb.query_one(
                'select token, UNIX_TIMESTAMP(`token_expire_time`) as token_expire_time from tdp_user where id=%s',
                user_id
            )
            if user_info:
                await self.mdb.update_by_dict(
                    table='tdp_user',
                    colv={'user_name': user_name, 'real_name': real_name},
                    where={'id': user_id}
                )
                if user_info['token_expire_time'] > time.time():
                    sso_cli_token = user_info['token']
                else:
                    sso_cli_token = await self.update_user_token(
                        token_info={'i': user_id, 'n': user_name, 'rn': real_name},
                        user_id=user_id
                    )
            else:
                await self.mdb.insert_by_dict(
                    table='tdp_user',
                    data={
                        'id': user_id,
                        'user_name': user_name,
                        'real_name': real_name,
                        'token': self.encryption.token_enc({'id': user_id, 'name': user_name, 'ctime': time.time()}),
                        'passwd': self.encryption.passwd_enc(f'{user_id}@.sso'),
                        # 'token_expire_time': (datetime.datetime.now() + datetime.timedelta(hours=5)).strftime(
                        #                         #     "%Y-%m-%d %H:%M:%S")
                    }
                )
                sso_cli_token = await self.update_user_token(
                    token_info={'i': user_id, 'n': user_name, 'rn': real_name},
                    user_id=user_id
                )
            self.set_cookie('token', sso_cli_token)
            self.success_data = sso_cli_token


class UserLogoutHandler(BaseRequestHandler):
    pass


class CurrentUser(BaseRequestHandler):
    async def get_default(self):
        self.success_data = self.user_info


